home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue53 / Multicas / Example1 / UnitMulticaster.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1999-10-14  |  4.7 KB  |  166 lines

  1. unit UnitMulticaster;
  2. interface
  3. uses SysUtils, Classes;
  4. type
  5.  
  6.   TMethodReference = procedure of object;
  7.   TMethodReferenceList = class(TObject)
  8.   private
  9.     FList: TList;
  10.   protected
  11.     procedure Add(aMethodReference: TMethodReference);
  12.     procedure Remove(aMethodReference: TMethodReference);
  13.     procedure Clear;
  14.   public
  15.     constructor Create;
  16.     destructor Destroy; override;
  17.     procedure RemoveAllForAnObject(anObject: TObject);
  18.   end;
  19.  
  20.   TEvent = class(TObject)
  21.   private
  22.     FSender: TObject;
  23.   public
  24.     constructor Create(aSender: TObject);
  25.     property Sender: TObject read FSender;
  26.   end;
  27.  
  28.   TEventAfterChange = class(TEvent);
  29.  
  30.   TEventListener = procedure(aMulticasterEvent: TEvent) of object;
  31.   TEventMulticaster = class(TMethodReferenceList)
  32.   public
  33.     procedure AddListener(aMulticasterEventListener: TEventListener);
  34.     procedure RemoveListener(aMulticasterEventListener: TEventListener);
  35.     procedure Broadcast(aMulticasterEvent: TEvent);
  36.   end;
  37.  
  38. implementation
  39.  
  40. { TEventMulticaster }
  41.  
  42. procedure TEventMulticaster.AddListener(aMulticasterEventListener: TEventListener);
  43. begin
  44.   Add(TMethodReference(aMulticasterEventListener));
  45. end;
  46.  
  47. procedure TEventMulticaster.Broadcast(aMulticasterEvent: TEvent);
  48. var i: integer;
  49. var pMulticasterEventListener: ^TEventListener;
  50. begin
  51.   try
  52.   for i := 0 to (FList.Count - 1) do
  53.     begin
  54.       pMulticasterEventListener := FList.Items[i];
  55.       pMulticasterEventListener^(aMulticasterEvent);
  56.     end;
  57.   finally
  58.   aMulticasterEvent.Free;
  59.   end; //  try..finally
  60. end;
  61.  
  62. procedure TEventMulticaster.RemoveListener(aMulticasterEventListener: TEventListener);
  63. begin
  64.   Remove(TMethodReference(aMulticasterEventListener));
  65. end;
  66.  
  67. { TMethodReferenceList }
  68.  
  69. procedure TMethodReferenceList.Add(aMethodReference: TMethodReference);
  70. var pMethodReference: ^TMethodReference;
  71. var i: integer;
  72. begin
  73.   // Look at each method in the collection to see if aMethodReference has
  74.   // already been added.
  75.   for i := 0 to (FList.Count - 1) do
  76.   begin
  77.     // Put the untyped FList pointer into the typed method reference pointer.
  78.     pMethodReference := FList.Items[i];
  79.     // Don't do anything if the method reference has already been stored.
  80.     if    ( TMethod(pMethodReference^).Code = TMethod(aMethodReference).Code )
  81.       and ( TMethod(pMethodReference^).Data = TMethod(aMethodReference).Data )
  82.       then exit;
  83.   end;
  84.   // If we get this far we're adding a new method reference. First allocate
  85.   // space to store the saved reference.
  86.   New(pMethodReference);
  87.   // Now save the method reference data in the new space.
  88.   pMethodReference^ := aMethodReference;
  89.   // Finally, save the address of the method reference data in the TList.
  90.   FList.Add(pMethodReference);
  91. end;
  92.  
  93. procedure TMethodReferenceList.Clear;
  94. var pMethodReference: ^TMethodReference;
  95. begin
  96.   while (FList.Count > 0) do
  97.   begin
  98.     pMethodReference := FList.Items[0];
  99.     Dispose(pMethodReference);
  100.     FList.Delete(0);
  101.   end;
  102. end;
  103.  
  104. constructor TMethodReferenceList.Create;
  105. begin
  106.   inherited;
  107.   FList := TList.Create;
  108. end;
  109.  
  110. destructor TMethodReferenceList.Destroy;
  111. begin
  112.   Clear;
  113.   FList.Free;
  114.   inherited;
  115. end;
  116.  
  117. procedure TMethodReferenceList.Remove(aMethodReference: TMethodReference);
  118. var pMethodReference: ^TMethodReference;
  119. var i: integer;
  120. begin
  121.   // Look at each method in the collection.
  122.   for i := (FList.Count - 1) downto 0 do
  123.   begin
  124.     // Put the untyped FList pointer into the typed method reference pointer.
  125.     pMethodReference := FList.Items[i];
  126.     // If the method reference is found then de-allocate its memory and remove
  127.     // the reference from FList.
  128.     if    ( TMethod(pMethodReference^).Code = TMethod(aMethodReference).Code )
  129.       and ( TMethod(pMethodReference^).Data = TMethod(aMethodReference).Data ) then
  130.     begin
  131.       Dispose(pMethodReference);
  132.       FList.Delete(i);
  133.       exit;
  134.     end;
  135.   end;
  136. end;
  137.  
  138. procedure TMethodReferenceList.RemoveAllForAnObject(anObject: TObject);
  139. var pMulticasterEventListener: ^TEventListener;
  140. var i: integer;
  141. begin
  142.   // Look at each method in the collection.
  143.   for i := (FList.Count - 1) downto 0 do
  144.   begin
  145.     // Put the untyped FList pointer into the typed method reference pointer.
  146.     pMulticasterEventListener := FList.Items[i];
  147.     // If any procedure or function reference is associated with the passed
  148.     // object then de-allocate its memory and remove the reference from FList.
  149.     if    ( TMethod(pMulticasterEventListener^).Data = anObject ) then
  150.     begin
  151.       Dispose(pMulticasterEventListener);
  152.       FList.Delete(i);
  153.     end; // then begin
  154.   end; // do begin
  155. end;
  156.  
  157. { TEvent }
  158.  
  159. constructor TEvent.Create(aSender: TObject);
  160. begin
  161.   inherited Create;
  162.   FSender := aSender;
  163. end;
  164.  
  165. end.
  166.